//Class TC Transport channel
import java.io.*;
import java.net.*;
import java.util.Arrays;

public class TC {
	
	//ATTRIBUTI CLASSE 
	DatagramSocket serverTC;

	//METODI CLASSE
	public void startTC() {
		try {
			serverTC = new DatagramSocket(65432);
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
	
	public void runTC() {
		byte[] receiveData = new byte[10000];
		Contatore cont = new Contatore();
		while(true) {
			try {
				
				DatagramPacket receivedPacket = new DatagramPacket(receiveData, receiveData.length);
				
				this.serverTC.receive(receivedPacket);
				
				ParallelTC parallelTC = new ParallelTC(receivedPacket, cont);
				
				Thread thread = new Thread(parallelTC);
				
				thread.run();
				
			} catch(IOException e) {
				e.printStackTrace();
			}
		}
	}
	private class Contatore{
		private long ricevuti;
		private long droppati;
		
		public Contatore(){
			this.ricevuti=0;
			this.droppati=0;
		}	
		public long getRicevuti(){
			return this.ricevuti;
		}
		public long getDroppati(){
			return this.droppati;
		}
		public void setRicevuti(){
			this.ricevuti++;
		}
		public void setDroppati(){
			this.droppati++;
		}
	}
	private class ParallelTC implements Runnable {
		
		private DatagramPacket packet;
		private Contatore cont;
		
		public ParallelTC(DatagramPacket client, Contatore cont){
			this.packet = client;
			this.cont = cont;
    }
    public void run(){
    	try {
    		this.cont.setRicevuti();
    		Packet rec = new Packet(packet.getData());
    		int L = rec.getLength()+16;
    		double prob = 1-Math.exp((double)-L/1024);
    		double rand = Math.random();
            if (rand > prob) {
            	//System.out.println("Dormo");
            	long tau = Math.round(1024/Math.log(L));
        		long t = Math.round(-tau*Math.log(Math.random()));
            	Thread.sleep(t);
            	InetAddress IPAddressDest = rec.getIPDestination();
                int port = rec.getPortDestination();
            	byte[] s = rec.toByte();
            	//System.out.println(rec.getPortSource()+"---->"+rec.getPortDestination());
                DatagramPacket sendPacket = new DatagramPacket(s, s.length, IPAddressDest, port);
                serverTC.send(sendPacket); 
            }
            else {
            	this.cont.setDroppati();
            }
            } catch(Exception e) {
    			e.printStackTrace();
    	}
    	System.out.println("Pacchetti droppati: "+this.cont.getDroppati() + "Pacchetti ricevuti: " + this.cont.getRicevuti());
    }
     }
   }






